package com.gwtintegration.smartrf.builder;

import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.core.ext.typeinfo.JMethod;
import com.google.gwt.user.rebind.SourceWriter;

public class CompositePrimaryKeyFieldConverterBuilder extends FieldConverterBuilder {

	protected CompositePrimaryKeyFieldConverterBuilder(JMethod getterMethod, ProxyConverterBuilder proxyConverterBuilder) {
		super(getterMethod, proxyConverterBuilder);
	}

	@Override
	public boolean buildToProxy(SourceWriter sourceWriter) throws UnableToCompleteException {

		if (!hasSetterMethod()) {
			return false;
		}

		JMethod setterMethod = getSetterMethod();
		JMethod getterMethod = getGetterMethod();
		JClassType parameterType = JMethodUtils.getSingleParameterType(setterMethod);

		sourceWriter.println("proxy.%s(null);", setterMethod.getName());

		for (JMethod primaryKeyMethod : parameterType.getMethods()) {

			if (!JMethodUtils.isSetter(primaryKeyMethod)) {
				continue;
			}

			JClassType compositeParameterType = JMethodUtils.getSingleParameterType(primaryKeyMethod);

			if (JTypeUtils.isPrimitive(compositeParameterType)) {

				String compositeProxyVarName = JMethodUtils.getVariableName(primaryKeyMethod);
				String compositeAttrName = JMethodUtils.getAttributeName(primaryKeyMethod);

				extractPrimitiveRecordAttribute(sourceWriter, compositeProxyVarName, compositeAttrName, compositeParameterType);
				sourceWriter.println("if(%s != null) {", compositeProxyVarName);
				sourceWriter.indent();

				sourceWriter.println("if(proxy.%s() == null) {", getterMethod.getName());
				sourceWriter.indentln("proxy.%s(requestContext.create(%s.class));", setterMethod.getName(), parameterType.getQualifiedSourceName());
				sourceWriter.println("}");

				sourceWriter.println("proxy.%s().%s(%s);", getterMethod.getName(), primaryKeyMethod.getName(), compositeProxyVarName);

				sourceWriter.outdent();
				sourceWriter.println("}");
				sourceWriter.println();

			} else {
				getProxyConverterBuilder().getLogger().equals(
						"Invalid type inside composite primary key of proxy " + getProxyConverterBuilder().getProxyType().getQualifiedSourceName()
								+ ".");
				throw new UnableToCompleteException();
			}
		}

		return true;
	}

	@Override
	public boolean buildToRecord(SourceWriter sourceWriter) throws UnableToCompleteException {

		JMethod getterMethod = getGetterMethod();
		JClassType returnType = getterMethod.getReturnType().isClassOrInterface();

		for (JMethod primaryKeyMethod : returnType.getMethods()) {

			if (!JMethodUtils.isGetter(primaryKeyMethod)) {
				continue;
			}

			JClassType compositeReturnType = primaryKeyMethod.getReturnType().isClassOrInterface();

			if (JTypeUtils.isPrimitive(compositeReturnType)) {

				String compositeProxyVarName = JMethodUtils.getVariableName(primaryKeyMethod);
				String compositeAttrName = JMethodUtils.getAttributeName(primaryKeyMethod);

				sourceWriter.println("%s %s = proxy.%s() != null ? proxy.%s().%s() : null;", compositeReturnType.getName(), compositeProxyVarName,
						getterMethod.getName(), getterMethod.getName(), primaryKeyMethod.getName());

				sourceWriter.println("if(%s != null) {", compositeProxyVarName);
				sourceWriter.indent();
				sourceWriter.println("record.setAttribute(\"%s\", %s);", compositeAttrName, compositeProxyVarName);
				sourceWriter.outdent();
				sourceWriter.println("}");
				sourceWriter.println();

			} else {
				getProxyConverterBuilder().getLogger().equals(
						"Invalid type inside composite primary key of proxy " + getProxyConverterBuilder().getProxyType().getQualifiedSourceName()
								+ ".");
				throw new UnableToCompleteException();
			}
		}

		return true;
	}

	@Override
	public boolean buildEquals(SourceWriter sourceWriter) throws UnableToCompleteException {

		JMethod getterMethod = getGetterMethod();
		JClassType returnType = getterMethod.getReturnType().isClassOrInterface();

		for (JMethod primaryKeyMethod : returnType.getMethods()) {

			if (!JMethodUtils.isGetter(primaryKeyMethod)) {
				continue;
			}

			JClassType compositeReturnType = primaryKeyMethod.getReturnType().isClassOrInterface();

			if (JTypeUtils.isPrimitive(compositeReturnType)) {

				String compositeProxyVarName = JMethodUtils.getVariableName(primaryKeyMethod);
				String compositeRecordVarName = compositeProxyVarName + "Attr";
				String compositeAttrName = JMethodUtils.getAttributeName(primaryKeyMethod);

				extractPrimitiveRecordAttribute(sourceWriter, compositeRecordVarName, compositeAttrName, compositeReturnType);
				sourceWriter.println("%s %s = proxy.%s() != null ? proxy.%s().%s() : null;", compositeReturnType.getName(), compositeProxyVarName,
						getterMethod.getName(), getterMethod.getName(), primaryKeyMethod.getName());

				sourceWriter.println("if (%s == null) {", compositeProxyVarName);
				sourceWriter.indent();
				sourceWriter.println("if (%s != null) {", compositeRecordVarName);
				sourceWriter.indentln("return false;");
				sourceWriter.println("}");
				sourceWriter.outdent();
				sourceWriter.println("} else if (!%s.equals(%s)) {", compositeProxyVarName, compositeRecordVarName);
				sourceWriter.indentln("return false;");
				sourceWriter.println("}");
				sourceWriter.println();

			} else {
				getProxyConverterBuilder().getLogger().equals(
						"Invalid type inside composite primary key of proxy " + getProxyConverterBuilder().getProxyType().getQualifiedSourceName()
								+ ".");
				throw new UnableToCompleteException();
			}
		}

		return true;
	}
}
